package com.jsg.sl651.entity.frame.body;

import com.jsg.sl651.entity.frame.body.report.*;
import com.jsg.sl651.entity.frame.header.Function;
import com.jsg.sl651.enums.CommunicationMessageType;
import com.jsg.sl651.exception.MessageBodyCodeException;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;

/**
 * MessageBody工厂
 */
@Slf4j
public final class MessageBodyFactory {

    public static Map<Integer, Class<? extends MessageBody>> MESSAGE_BODY_MAP = new HashMap<Integer, Class<? extends MessageBody>>();

    static {
        register(LinkMaintenanceReport.class);
        register(TestReport.class);
        register(TelemetryTimingReport.class);
        register(UniformHydroInfoReport.class);
        register(RemoteTelemetryStationReporting.class);
        register(ShortReportOfTelemetryStation.class);
    }
    public static void register(Class<? extends MessageBody> clazz) {
        try {
            MessageBody messageBody = clazz.newInstance();
            if (MESSAGE_BODY_MAP.containsKey(messageBody.getFunctionCode())) {
                log.warn("方法ID - {} 的处理器已经注册，当前注册操作将会代替原本处理器，请知悉。 原本处理器： {}， 替换后处理器：{}", messageBody.getFunctionCode(), MESSAGE_BODY_MAP.get(messageBody.getFunctionCode()).getName(), clazz.getName());
            }
            MESSAGE_BODY_MAP.put(messageBody.getFunctionCode(), clazz);
        } catch (Exception e) {
            throw new RuntimeException("MessageBodyFactory 注册失败："+ e.getMessage());
        }
    }


    public static MessageBody decode(CommunicationMessageType type, Function function, byte[] bytes) throws Exception {
        Class<? extends MessageBody> aClass = MESSAGE_BODY_MAP.get(function.getCode());
        if (aClass == null) {
            throw new MessageBodyCodeException("MessageBodyFactory 解码失败：未找到对应的MessageBody处理器");
        }
        MessageBody messageBody = aClass.newInstance();
        return messageBody.decode(type, bytes);
    }

    public static byte[] encode(MessageBody messageBody, CommunicationMessageType type) {
        return messageBody.encode(type);
    }

}
